#pragma once
#include <iostream>
#include "include/mysql.h"
#include <string>
#include <jsoncpp/json/json.h>
#include <fstream>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <memory>

#include "log_util.hpp"
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>


typedef websocketpp::server<websocketpp::config::asio> wsserver_t;


class Mysql_Util
{
public:
    static MYSQL* mysql_create(const std::string host, const std::string user, 
        const std::string passwd, const std::string db, int port)
    {
        MYSQL* mysql = mysql_init(NULL);
        if(mysql == NULL)
        {
            LOG(ERROR) << "创建mysql句柄失败" << "\n";
            return NULL;
        }
        if(NULL == mysql_real_connect(mysql, host.c_str(), user.c_str(), 
        passwd.c_str(), db.c_str(), port, NULL, 0))
        {
            LOG(ERROR) << "连接数据库失败" << "\n";
            std::cerr << mysql_error(mysql) << std::endl;
            mysql_close(mysql);
            return NULL;
        }
        mysql_set_character_set(mysql, "utf8");
        return mysql;                             
    }
    static bool mysql_exe(MYSQL* mysql, const std::string& sql)
    {
        if(0 != mysql_query(mysql, sql.c_str()))
        {
            LOG(ERROR) << "执行sql语句失败" << "\n";
            std::cerr << mysql_error(mysql) << std::endl;
            return false;
        }
        return true;
    }
    static void mysql_des(MYSQL* mysql)
    {
        if(mysql != NULL)
        {
            mysql_close(mysql);
        }
    }
};

class Json_Util
{
public:
    static bool serializa(const Json::Value &root, std::string& str)
    {
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        std::stringstream ss;
        int ret = sw->write(root, &ss);//==0成功
        if(ret != 0)
        {
            LOG(ERROR) << "序列化失败" << "\n";
            return false;
        }
        str = ss.str();
        return true;
    }
    static bool unserializa(const std::string& str, Json::Value& root)
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
        std::string err;
        bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
        if(!ret) 
        {
            LOG(ERROR) << "反序列化失败" << "\n";
            return false;
        }
        return true;
    }
};

class File_Util
{
public:
    static bool ReadFile(const std::string& file, std::string& content)
    {
        std::ifstream in(file, std::ios::binary);
        if(!in.is_open())
        {
            LOG(ERROR) << "打开文件失败" << "\n";
            return false;
        }
        // 移动文件指针位置，为了确定文件大小
        in.seekg(0, std::ios::end);
        std::size_t size = in.tellg();
        in.seekg(0, std::ios::beg);

        content.resize(size);
        in.read(&content[0], size);
        if(!in.good())
        {
            LOG(ERROR) << "读取文件信息失败" << "\n";
            in.close();
            return false;
        }
        in.close();
        return true;
    }
};

class Split_Util
{
public:
    static void splitStr(const std::string& str, std::vector<std::string>* v, const std::string& sep)
    {
        boost::split(*v, str, boost::is_any_of(sep), boost::algorithm::token_compress_on);
    }
};
